'''
    二进制在运算中的说明
    1.二进制是逢2进位的进位制,0,1是基本的数字符号
    2.现代的电子计算机技术全部采用的是二进制,因为他只使用0,1两个数字符号，非常简单方便，易于电子方式实现
    3.计算机内部处理的信息,都是采用二进制来表示的，二进制(Binary)数用0和1两个数字及其组合来表示任何数
        进制规则是"逢2进1"，数字1在不同的位上代表不同的值
    书上写的原码,反码,补码的解释过于复杂,精简几句

    反码 ： 符号位不变  其他的0变1  1变0


    1.二进制的最高位是符号位:0表示正数,1表示负数
    我们下面假定一个字节来表示
        3 => 0000 0011
       -3 => 1000 0011

   2.正数的原码，反码，补码都是一样的(三码合一)
       3 => 原码 : 0000 0011
            反码 : 0000 0011
            补码 : 0000 0011
   3.负数的原码，反码，补码都是不一样的
        反码 ： 符号位不变  其他的0变1  1变0
        -3 => 原码 : 1000 0011
              反码 : 1111 1100
   4.负数的补码=它的反码+1 ， 负数的反码 = 负数的补码 - 1
        -3 => 原码 : 1000 0011
              反码 : 1111 1100
              补码 : 1111 1101
   5.0的反码，补码都是0
   6.在计算机运行的时候,都是以补码的方式来运行的
       1 + 3 => 4
       1 => 补码 0000 0001 【正数三码合一】
       3 => 补码 0000 0011 【正数三码合一】
       1 + 3补码 0000 0100  补码【逢2进1】 因为是正数 所以 三码合一 补码=原码  = 4

   7.当我们看运算结果的时候，要看他的原码

   例子1：
    1 - 3 => -2 【这就是原理，基本不用去看，但是要是老师讲到了，就好好的学一下】
    1 => 补码 0000 0001 【三码合一】
   -3 => 原码 1000 0011 => 反码 1111 1100 => 补码 : 1111 1101
   1 - 3 => 1 + (-3)
   1补码: 0000 0001
  -3补码: 1111 1101
         1111 1110【补码】 => 反码 1111 1101 => 原码 : 1000 0010  转换成十进制 -2
    & | ^ ~
'''

'''
 ~
 规则: 对于每个二进制取反，即把0变为1，把1变为0
    分析 ~-2 , ~2的结果是多少
    
    我们假定使用一个字节来表示
    ~-2 = ?
    -2的补码=  1111 1110 => (-2原码) 1000 0010 => (-2的反码) 1111 1101 => (-2的补码) 1111 1110
    ~-2【取反】0000 0001(补码) => 0000 0001(原码)【三码合一】   = 转换成2进制 1 
    
    ~2 = ?
     2的补码 0000 0010 【三码合一】 
     取反    1111 1101(补码) =>  1111 1100(反码) => 原码 1000 0011 = -3
     自己看出来了  说明确实懂了
'''


print(~-2)#1
print(~2)

'''
    按位与AND
    &规则：参与运算的两个值,如果两个相应的值都是1，则该位的结果是1，否则为0
    分析2&3的结果是多少?
    2 & 3=?
    2的补码 0000 0010
    3的补码 0000 0011
    2 & 3  0000 0010(补码) => 0000 0010(原码) 三码合一 2
'''
#咱知道原理是这样 最后是这样算出来的  但是咱要一眼看出来 2 & 3 就是返回第一个数
#其实在真的工作中没有什么用  但是将来别人问的时候咱要知道  能起关键性作用  现在了解即可
#你直接是看不出来的 这个需要计算  你要知道原理，别人问的时候你要知道 真的要知道结果 你只需要去测试
#并且这个不常用
print(2 & 3)

'''
    3. ^按位异或
    ^规则：当两个对应的二进制相异的时候，结果为1
    分析 2 ^ -3的结果是多少？
    我不知道，猜是猜不出来的
    2 ^ -3 = ?
    2的补码    0000 0010
   -3的补码：   1111 1101   原码 ： 1000 0011 => 反码 : 1111 1100 => 补码 1111 1101
   2^-3       1111 1111 (补码) : 1111 1110(反码) => 1000 0001 => 转成二进制 -1
   我知道怎么运算 也知道运算的结果 可是在工作中确实用不上 但是咱必须懂
   复杂的东西咱都能懂 简单的就更加没有问题了
'''
print(2 ^ -3)

'''
    | 按位或
    | 规则：只要对应的二个二进制有一个为1的时候，结果位就是1
    这个知识点实在是太多了  但是这个很重要  有助于理解计算机的运行原理
    2 | 3
    2(补码) 0000 0010
    3(补码) 0000 0011
    2|3    0000 0011(补码) => 0000 0011(原码) => 3
    
'''
print(2 | 3)

'''
<<左移
<< 左移规则，运算数的各二进制位全部左移若干位，由 << 右边的数指定移动的位数,符号位不变,高位丢弃，低位补0
5的原码:0000 0101
1的原码:0000 0001
5 << 1 = ?
5的补码 0000 0101
5 << 1 : 00001010(补码) => 00001010(原码) => 10    其实相当于 5*2

-5 << 1 补码:1111 1011 原码1000 0101 => 1111 1010(反码) => 1111 1011(补码)
-5的补码 
补码  : 1111 1011
-5<<1  1111 0110(补码) => 1111 0101 (反码) => 1000 1010 => -10  其实相当于-5*2
'''
print(5 << 1)#10
print(-5 << 1)#-10


'''
>>规则:把>>左边的运算数的各二进制全部右移若干位,">>" 右边的数指定移动的位数,低位溢出【意思就是不要了】
符号位不变，并用符号位补溢出的高位【指的就是左边的位置】
5 >> 1 = ?
5:原码 0000 0101
 补码  0000 0101
5>>1  00000010 (补码) 原码(00000010) => 2  相当于 5 // 2

-5 >> 1 = ?
原码 -5 ：  1000 0101
补码   :  1111 1011  ? => 1111 1010(反码) => 1111 1011 (补码)
-5 >> 1 : 1111 1101(补码) => 1111 1100(反码) => 1000 0011 => 转化成二进制 -3 相当于 -5 // 2 = -3 
'''
print(5 >> 1)
print(-5 >> 1) #-3







